﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace RIO.Utilits
{
  public class IniFile
  {
    [DllImport("KERNEL32.DLL",
                    EntryPoint = "WritePrivateProfileStringW",
                    SetLastError = true,
                    CharSet = CharSet.Unicode,
                    ExactSpelling = true,
                    CallingConvention = CallingConvention.StdCall)]
    private static extern long WritePrivateProfileString(string category,
        string key, string value, string filepath);

    [DllImport("KERNEL32.DLL",
                EntryPoint = "GetPrivateProfileStringW",
                SetLastError = true,
                CharSet = CharSet.Unicode,
                ExactSpelling = true,
                CallingConvention = CallingConvention.StdCall)]
    private static extern int GetPrivateProfileString(string category,
        string key, string def, StringBuilder returnvalue, int size, string filepath);

    [DllImport("KERNEL32.DLL",
                EntryPoint = "GetPrivateProfileStringW",
                SetLastError = true,
                CharSet = CharSet.Unicode,
                ExactSpelling = true,
                CallingConvention = CallingConvention.StdCall)]
    private static extern int GetPrivateProfileString(string category,
            string key, string def, string returnvalue, int size, string filepath);

    public string FilePath;

    public IniFile(string filePath)
    {
      FilePath = filePath;
    }

    /// <summary>
    /// Write to .ini file.
    /// </summary>
    /// <param name="category">The name of the category to write to, if it doesn't exist it will create the category.</param>
    /// <param name="key">The name of the key, if it doesn't exist it will create the key.</param>
    /// <param name="value">The value of the specified key.</param>
    /// <param name="filepath">The filepath including the file. Example "C:\\test.ini"</param>
    public void IniWriteValue(string category, string key, string value)
    {
      WritePrivateProfileString(category, key, value, FilePath);
    }
    /// <summary>
    /// Read from .ini file.
    /// </summary>
    /// <param name="category">The name of the category to read from.</param>
    /// <param name="key">The name of the key to read.</param>
    /// <param name="filepath">The filepath including the file. Example "C:\\test.ini"</param>
    /// <returns>The value from the specified category and key.</returns>
    public string IniReadValue(string category, string key)
    {
      StringBuilder result = new StringBuilder(255);
      int i = GetPrivateProfileString(category, key, "", result, 255, FilePath);

      return result.ToString();
    }

    /// <summary>
    /// Get all categories from a .ini file.
    /// </summary>
    /// <param name="filepath">The filepath including the file. Example "C:\\test.ini"</param>
    /// <returns>A List of all categories in the specified file.</returns>
    public List<string> IniGetCategories()
    {
      string returnString = new string(' ', 65536);

      GetPrivateProfileString(null, null, null, returnString, 65536, FilePath);

      List<string> result = new List<string>(returnString.Split('\0'));
      result.RemoveRange(result.Count - 2, 2);
      return result;
    }

    /// <summary>
    /// Get all keys from a category in a .ini file.
    /// </summary>
    /// <param name="category">The name of the category to read from.</param>
    /// <param name="filepath">The filepath including the file. Example "C:\\test.ini"</param>
    /// <returns>A list of all keys in the specified category from the .ini file.</returns>
    public List<string> IniGetKeys(string category)
    {
      string returnString = new string(' ', 32768);

      GetPrivateProfileString(category, null, null, returnString, 32768, FilePath);

      List<string> result = new List<string>(returnString.Split('\0'));
      result.RemoveRange(result.Count - 2, 2);
      return result;
    }

  }
}
